module apb_subsystem_top #(
    parameter       ADDRWIDTH = 16)
    (
    input  wire                 HCLK,
    input  wire                 HRESETn,

    input  wire                 HSEL,       // Device select
    input  wire [ADDRWIDTH-1:0] HADDR,      // Address
    input  wire           [1:0] HTRANS,     // Transfer control
    input  wire           [2:0] HSIZE,      // Transfer size
    input  wire           [3:0] HPROT,      // Protection control
    input  wire                 HWRITE,     // Write control
    input  wire                 HREADY,     // Transfer phase done
    input  wire          [31:0] HWDATA,     // Write data
    output wire                 HREADYOUT,  // Device ready
    output wire          [31:0] HRDATA,     // Read data output
    output wire                 HRESP,      // Device response
    
    input  wire                 PCLK,       
    input  wire                 PCLKG,      //gated PCLK
    input  wire                 PCLKEN,     //clk enable for APB interface
    input  wire           [3:0] PRESETn,    //
    output wire                 APBACTIVE,
    // UART signal
    input  wire                 RXD,
    output wire                 TXD,
    output wire                 TXEN,
    // SBCon signal
    input  wire                 SDA,
    output wire                 SCL,
    output wire                 SDAOUTEN_n,
    // interrupt
    output wire                 TXINT,      // Transmit Interrupt
    output wire                 RXINT,      // Receive Interrupt
    output wire                 TXOVRINT,   // Transmit overrun Interrupt
    output wire                 RXOVRINT,   // Receive overrun Interrupt
    output wire                 UARTINT,    // Combined interrupt
    output wire                 TIMERINT    // Timer interrupt
    );
    
wire    [ADDRWIDTH-1:0] PADDR;
wire                    PENABLE;
wire                    PWRITE;
wire              [3:0] PSTRB;
wire              [2:0] PPROT;
wire             [31:0] PWDATA;
wire                    PSEL;
wire             [31:0] PRDATA;
wire                    PREADY;
wire                    PSLVERR;
cmsdk_ahb_to_apb 
#(
    .ADDRWIDTH      (ADDRWIDTH      ),
    .REGISTER_RDATA (1'b0           ),
    .REGISTER_WDATA (1'b0           )
)
u_cmsdk_ahb_to_apb(
    .HCLK      (HCLK      ),
    .HRESETn   (HRESETn   ),
    .PCLKEN    (PCLKEN    ),
    //
    .HSEL      (HSEL      ),
    .HADDR     (HADDR     ),
    .HTRANS    (HTRANS    ),
    .HSIZE     (HSIZE     ),
    .HPROT     (HPROT     ),
    .HWRITE    (HWRITE    ),
    .HREADY    (HREADY    ),
    .HWDATA    (HWDATA    ),
    .HREADYOUT (HREADYOUT ),
    .HRDATA    (HRDATA    ),
    .HRESP     (HRESP     ),
    //
    .PADDR     (PADDR     ),
    .PENABLE   (PENABLE   ),
    .PWRITE    (PWRITE    ),
    .PSTRB     (PSTRB     ),
    .PPROT     (PPROT     ),
    .PWDATA    (PWDATA    ),
    .PSEL      (PSEL      ),
    .APBACTIVE (APBACTIVE ),
    //
    .PRDATA    (PRDATA    ),
    .PREADY    (PREADY    ),
    .PSLVERR   (PSLVERR   )
);

wire        PSEL0;
wire        PREADY0;
wire [31:0] PRDATA0;
wire        PSLVERR0;
wire        PSEL1;
wire [31:0] PRDATA1;
wire        PSEL2;
wire        PREADY2;
wire [31:0] PRDATA2;
wire        PSLVERR2;

cmsdk_apb_slave_mux 
#(
    .PORT0_ENABLE  (1'b1  ),
    .PORT1_ENABLE  (1'b1  ),
    .PORT2_ENABLE  (1'b0  ),
    .PORT3_ENABLE  (1'b0  ),
    .PORT4_ENABLE  (1'b0  ),
    .PORT5_ENABLE  (1'b0  ),
    .PORT6_ENABLE  (1'b0  ),
    .PORT7_ENABLE  (1'b0  ),
    .PORT8_ENABLE  (1'b0  ),
    .PORT9_ENABLE  (1'b0  ),
    .PORT10_ENABLE (1'b0 ),
    .PORT11_ENABLE (1'b0 ),
    .PORT12_ENABLE (1'b0 ),
    .PORT13_ENABLE (1'b0 ),
    .PORT14_ENABLE (1'b0 ),
    .PORT15_ENABLE (1'b0 )
)
u_cmsdk_apb_slave_mux(
    .DECODE4BIT (PADDR[ADDRWIDTH-1:ADDRWIDTH-4] ),
    .PSEL       (PSEL       ),
    .PREADY     (PREADY     ),
    .PRDATA     (PRDATA     ),
    .PSLVERR    (PSLVERR    ),
    // UART slave
    .PSEL0      (PSEL0      ),
    .PREADY0    (PREADY0    ),
    .PRDATA0    (PRDATA0    ),
    .PSLVERR0   (PSLVERR0   ),
    // SBCon slave
    .PSEL1      (PSEL1      ),
    .PREADY1    (1'b1       ),
    .PRDATA1    (PRDATA1    ),
    .PSLVERR1   (1'b0       ),
    // Timer slave
    .PSEL2      (PSEL2      ),
    .PREADY2    (PREADY2    ),
    .PRDATA2    (PRDATA2    ),
    .PSLVERR2   (PSLVERR2   ),
    // 
    .PSEL3      (PSEL3      ),
    .PREADY3    (PREADY3    ),
    .PRDATA3    (PRDATA3    ),
    .PSLVERR3   (PSLVERR3   ),
    .PSEL4      (PSEL4      ),
    .PREADY4    (PREADY4    ),
    .PRDATA4    (PRDATA4    ),
    .PSLVERR4   (PSLVERR4   ),
    .PSEL5      (PSEL5      ),
    .PREADY5    (PREADY5    ),
    .PRDATA5    (PRDATA5    ),
    .PSLVERR5   (PSLVERR5   ),
    .PSEL6      (PSEL6      ),
    .PREADY6    (PREADY6    ),
    .PRDATA6    (PRDATA6    ),
    .PSLVERR6   (PSLVERR6   ),
    .PSEL7      (PSEL7      ),
    .PREADY7    (PREADY7    ),
    .PRDATA7    (PRDATA7    ),
    .PSLVERR7   (PSLVERR7   ),
    .PSEL8      (PSEL8      ),
    .PREADY8    (PREADY8    ),
    .PRDATA8    (PRDATA8    ),
    .PSLVERR8   (PSLVERR8   ),
    .PSEL9      (PSEL9      ),
    .PREADY9    (PREADY9    ),
    .PRDATA9    (PRDATA9    ),
    .PSLVERR9   (PSLVERR9   ),
    .PSEL10     (PSEL10     ),
    .PREADY10   (PREADY10   ),
    .PRDATA10   (PRDATA10   ),
    .PSLVERR10  (PSLVERR10  ),
    .PSEL11     (PSEL11     ),
    .PREADY11   (PREADY11   ),
    .PRDATA11   (PRDATA11   ),
    .PSLVERR11  (PSLVERR11  ),
    .PSEL12     (PSEL12     ),
    .PREADY12   (PREADY12   ),
    .PRDATA12   (PRDATA12   ),
    .PSLVERR12  (PSLVERR12  ),
    .PSEL13     (PSEL13     ),
    .PREADY13   (PREADY13   ),
    .PRDATA13   (PRDATA13   ),
    .PSLVERR13  (PSLVERR13  ),
    .PSEL14     (PSEL14     ),
    .PREADY14   (PREADY14   ),
    .PRDATA14   (PRDATA14   ),
    .PSLVERR14  (PSLVERR14  ),
    .PSEL15     (PSEL15     ),
    .PREADY15   (PREADY15   ),
    .PRDATA15   (PRDATA15   ),
    .PSLVERR15  (PSLVERR15  )
);

 /***************************UART*****************************/

wire        BAUDTICK;
cmsdk_apb_uart u_cmsdk_apb_uart(
    .PCLK      (PCLK      ),
    .PCLKG     (PCLKG     ),
    .PRESETn   (PRESETn   ),
    //
    .PSEL      (PSEL0     ),
    .PADDR     (PADDR[ADDRWIDTH-5:2]),
    .PENABLE   (PENABLE   ),
    .PWRITE    (PWRITE    ),
    .PWDATA    (PWDATA    ),
    //
    .PRDATA    (PRDATA0   ),
    .PREADY    (PREADY0   ),
    .PSLVERR   (PSLVERR0  ),
    //
    .RXD       (RXD       ),
    .TXD       (TXD       ),
    .TXEN      (TXEN      ),
    .BAUDTICK  (BAUDTICK  ),
    //
    .TXINT     (TXINT     ),
    .RXINT     (RXINT     ),
    .TXOVRINT  (TXOVRINT  ),
    .RXOVRINT  (RXOVRINT  ),
    .UARTINT   (UARTINT   ),
    //
    .ECOREVNUM (4'd0      )
);

/***************************SBCon*****************************/

SBCon u_SBCon(
    .PCLK       (PCLK       ),
    .PRESETn    (PRESETn    ),

    .PSEL       (PSEL1      ),
    .PENABLE    (PENABLE    ),
    .PWRITE     (PWRITE     ),
    .PADDR      (PADDR[ADDRWIDTH-9:2]),
    .PWDATA     (PWDATA     ),
    .PRDATA     (PRDATA1    ),

    .SDA        (SDA        ),
    .SCL        (SCL        ),
    .SDAOUTEN_n (SDAOUTEN_n )
);

/***************************SBCon*****************************/

cmsdk_apb_timer u_timer(
    .PCLK      (PCLK      ),
    .PCLKG     (PCLKG     ),
    .PRESETn   (PRESETn   ),

    .PSEL      (PSEL2     ),
    .PENABLE   (PENABLE   ),
    .PWRITE    (PWRITE    ),
    .PADDR     (PADDR[ADDRWIDTH-5:2]),
    .PWDATA    (PWDATA    ),
    .PRDATA    (PRDATA2   ),
    .PREADY    (PREADY2   ),
    .PSLVERR   (PSLVERR2  ),

    .EXTIN     (1'b0      ),
    .TIMERINT  (TIMERINT  ),

    .ECOREVNUM (4'd0      )
);

endmodule